package ca.usherbrooke.domus.sipnmove.call.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import ca.usherbrooke.domus.sipnmove.call.Call;
import ca.usherbrooke.domus.sipnmove.sip.SipFacade;
import ca.usherbrooke.domus.sipnmove.sip.SipFacadeListener;

/**
 * Call that uses SIP for session initialization
 * 
 * A SIP call should act as a decorator over another call that handle data sharing (like RTP for example...).
 * 
 * This decorator is responsible of managing the session thanks to the SIP protocol.
 * After the session is initialized, hand is given to the decorated call to handle the real communication.
 * 
 * If session information is changed, the decorated call should be updated (via {@link Call::update}) 
 * or recreated or...
 */
public class SipCall implements Call, SipFacadeListener {

	/**
	 * SIP call listeners
	 */
	private Set<SipCallListener> sipCallListeners;
	
	/**
	 * Decorated call
	 */
	private Call decoratedCall;

	/**
	 * SIP facade
	 */
	private SipFacade sipFacade;

	/**
	 * SIP CallId associated to this call
	 */
	private String callId;
	
	/**
	 * Default constructor
	 */
	public SipCall(String callId) {
		sipCallListeners = new HashSet<SipCallListener>();
		this.callId = callId;
	}

	/**
	 * Add a SIP call listener
	 */
	public void addSipCallListener(SipCallListener sipCallListener)
	{
		sipCallListeners.add(sipCallListener);
	}
	
	/**
	 * Make a call ring
	 * 
	 * TODO : Define the parameters of this method
	 * TODO : This method should be placed in an implemented interface like PhoneCall or whatever
	 */
	public void ring()
	{
		
	}

	@Override
	public void accept() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void initiate(Map<String, Object> callInformation) {
		
		String toAdressString = (String) callInformation.get("address");
		sipFacade.sendInvite(toAdressString, callId);
	}

	@Override
	public void terminate() {
		this.decoratedCall.terminate();
		
		// FIXME: Should send a BYE
	}

	@Override
	public void update(Map<String, Object> callInformation) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void processAck(String callId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void processBye(String callId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void processOk(String callId) {

		// TODO: Replace that dirty thing ! Information is in SDP...
		Map<String, Object> callInformation = new HashMap<String, Object>();
		callInformation.put("ip", "10.44.164.57");
		callInformation.put("port", 3000);
		
		this.decoratedCall.initiate(callInformation);
		
		sipFacade.sendAck();
	}

	@Override
	public void processInvite(String callId) {
	}

	@Override
	public void processRinging(String callId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void processTrying(String callId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void processCancel(String callId) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * @return the decoratedCall
	 */
	public Call getDecoratedCall() {
		return decoratedCall;
	}

	/**
	 * @param decoratedCall the decoratedCall to set
	 */
	public void setDecoratedCall(Call decoratedCall) {
		this.decoratedCall = decoratedCall;
	}

	/**
	 * @return the sipFacade
	 */
	public SipFacade getSipFacade() {
		return sipFacade;
	}

	/**
	 * @param sipFacade the sipFacade to set
	 */
	public void setSipFacade(SipFacade sipFacade) {
		if(this.sipFacade != null)
			this.sipFacade.removeSipFacadeListener(this.callId);
	
		sipFacade.addSipFacadeListener(callId, this);
		this.sipFacade = sipFacade;
	}

}
